export const uniteKey = function (data, keys) {
  var k = keys[0];
  var v = data[k];
  var key = `${k}:${v}`;
  if (keys.length === 1) {
    return key;
  }
  for (var i = 1; i < keys.length; i++) {
    k = keys[i];
    v = data[k];
    key += `_${k}:${v}`;
  }
  return key;
};
export const cloneByKeys = function (data, keys) {
  if (
    data === undefined ||
    null === data ||
    keys === undefined ||
    null === keys ||
    keys.length === 0
  ) {
    return null;
  }
  var o = {};
  for (var i = 0; i < keys.length; i++) {
    const k = keys[i];
    o[k] = data[k];
  }
  return o;
};

const ListAnalysis = function (list) {
  if (!list || list.length === 0) {
    throw new Error("data is empty");
  }

  this.list = list;
  const that = this;

  function SummaryAnalysis(key) {
    this.key = key;
    this.result = {};
    this.list = [];
  }
  SummaryAnalysis.prototype.push = function (data) {
    const sumKey = this.key + "-sum";
    const countKey = this.key + "-count";
    const value = data[this.key];
    const valid = value !== undefined && value !== null;
    if (this.result[sumKey] === undefined) {
      this.result[sumKey] = valid ? value : 0;
      this.result[countKey] = valid ? 1 : 0;
      return;
    }
    this.result[sumKey] += valid ? value : 0;
    this.result[countKey] += valid ? 1 : 0;
  };
  SummaryAnalysis.prototype.execute = function () {
    return this.result;
  };
  function AvarageAnalysis(key) {
    this.list = [];
    this.key = key;
    this.sum = 0;
    this.count = 0;
    this.result = {};
  }
  AvarageAnalysis.prototype.push = function (data) {
    this.sum += data[this.key];
    this.count++;
  };
  AvarageAnalysis.prototype.execute = function () {
    this.result[this.key + "-avg"] = this.sum / this.count;
    return this.result;
  };

  const initAnalysis = function (analysis) {
    const list = [];
    if (!analysis || analysis.length === 0) {
      return list;
    }
    for (var i = 0; i < analysis.length; i++) {
      const each = analysis[i];
      if (typeof each === "string") {
        list.push(new SummaryAnalysis(each));
      } else {
        list.push(new each());
      }
    }
    return list;
  };
  this.groupBy = function (keys, analysisWithKey) {
    if (!keys || keys.length === 0) {
      throw new Error("keys is empty");
    }
    const analysisMap = {};
    for (var i = 0; i < this.list.length; i++) {
      const each = this.list[i];
      const key = uniteKey(each, keys);
      if (analysisMap[key] === undefined) {
        analysisMap[key] = {
          value: cloneByKeys(each, keys),
          list: [],
          analysis: initAnalysis(analysisWithKey),
        };
      }
      analysisMap[key].list.push(each);
      for (var a = 0; a < analysisMap[key].analysis.length; a++) {
        analysisMap[key].analysis[a].push(each);
      }
    }
    const list = [];
    const map = {};
    for (var key in analysisMap) {
      const { analysis, value } = analysisMap[key];
      value["unite_key"] = key;
      for (var i = 0; i < analysis.length; i++) {
        const result = analysis[i].execute();
        Object.assign(value, result);
      }
      map[key] = value;
      list.push(value);
    }
    return { list, map };
  };
};

export default ListAnalysis;
